<template>
  <el-dialog
    :model-value="modelValue"
    :title="title"
    :width="width + 'px'"
    :before-close="handleBeforeClose"
    destroy-on-close
    @update:model-value="handleUpdateVisible"
  >
    <el-form
      ref="formRef"
      :model="formData"
      :rules="props.rules"
      label-width="100px"
      size="default"
    >
      <el-form-item
        v-for="field in props.fields"
        :key="field.prop"
        :label="field.label"
        :prop="field.prop"
        :disabled="field.disabled"
        :required="field.required"
      >
        <template v-if="field.type === 'textarea'">
          <el-input
            v-model="formData[field.prop]"
            type="textarea"
            :rows="field.rows || 2"
            :placeholder="field.placeholder || `请输入${field.label}`"
            :disabled="field.disabled"
          />
        </template>
        <template v-else-if="field.type === 'select'">
          <el-select
            v-model="formData[field.prop]"
            :placeholder="field.placeholder || `请选择${field.label}`"
            :disabled="field.disabled"
            style="width: 100%"
          >
            <el-option
              v-for="option in field.options || []"
              :key="option.value"
              :label="option.label"
              :value="option.value"
            />
          </el-select>
        </template>
        <template v-else>
          <el-input
            v-model="formData[field.prop]"
            :placeholder="field.placeholder || `请输入${field.label}`"
            :disabled="field.disabled"
          />
        </template>
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="handleCancel">取消</el-button>
      <el-button type="primary" @click="handleConfirm">确认</el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, reactive, watch, computed } from "vue";
import type { FormInstance, FormRules } from "element-plus";

// 定义表单字段类型
interface FormField {
  label: string;
  prop: string;
  type?: "input" | "textarea" | "select";
  disabled?: boolean;
  required?: boolean;
  rows?: number;
  placeholder?: string;
  options?: Array<{ label: string; value: string }>;
}

// 定义组件props
interface Props {
  modelValue?: boolean;
  title?: string;
  width?: number;
  fields?: FormField[];
  initialForm?: Record<string, any>;
  rules?: FormRules;
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: false,
  title: "确认操作",
  width: 400,
  fields: () => [],
  initialForm: () => ({}),
  rules: () => ({}),
});

// 组件事件
const emit = defineEmits<{
  (e: "update:modelValue", value: boolean): void;
  (e: "confirm", formData: Record<string, any>): void;
  (e: "cancel"): void;
}>();

// 表单引用
const formRef = ref<FormInstance | null>(null);

// 表单数据
const formData = reactive<Record<string, any>>({ ...props.initialForm });

// 监听初始表单变化，同步更新
watch(
  () => props.initialForm,
  (newVal) => {
    Object.assign(formData, newVal);
  },
  { deep: true, immediate: true }
);

// 更新 visible 状态
const handleUpdateVisible = (value: boolean) => {
  emit("update:modelValue", value);
};

// 关闭前回调
const handleBeforeClose = () => {
  emit("update:modelValue", false);
};

// 取消操作
const handleCancel = () => {
  emit("update:modelValue", false);
  emit("cancel");
};

// 确认操作
const handleConfirm = async () => {
  if (!formRef.value) return;

  try {
    // 表单验证
    await formRef.value.validate();
    // 触发确认事件
    emit("confirm", { ...formData });
    // 关闭弹窗
    emit("update:modelValue", false);
  } catch (error) {
    // 验证失败不做处理
    return;
  }
};
</script>

<style scoped>
/* 弹窗内边距调整 */
:deep(.el-dialog__body) {
  padding: 20px;
}

/* 表单项间距调整 */
:deep(.el-form-item) {
  margin-bottom: 15px;
}
</style>
